#include "screen.h"
using namespace std;

void *touch_thread(void *argv) {
    Screen::INPUTEVENT inputEvent = {{0, 0}, 0, 0, 0};                   // 输入事件
    Screen::TOUCHEVENT touchEvent = {0, 0, 0, 0, 0, {0, 0}, {0, 0}};     // 触摸事件
    Screen::TIMEVAL time = {0, 0}, startTime = {0, 0}, endTime = {0, 0}; // 时间信息
    int32_t timeXY = -1, startX = -1, startY = -1, endX = -1, endY = -1; // 触摸坐标
    // 解析数据
    int32_t *touchFd = ((Screen::TOUCHPARAM *)argv)->touchFd;                              // 触摸指针
    pthread_t *touchTid = ((Screen::TOUCHPARAM *)argv)->touchTid;                          // 线程ID
    uint32_t *touchSignal = ((Screen::TOUCHPARAM *)argv)->touchSignal;                     // 触摸信号
    Screen::INPUTEVENT *touchInputEvent = ((Screen::TOUCHPARAM *)argv)->touchInputEvent;   // 触摸输入事件
    vector< Screen::TOUCHEVENT > *touchEvents = ((Screen::TOUCHPARAM *)argv)->touchEvents; // 触摸事件
    // 循环读取事件数据
    while (*touchSignal) {
        // 读取事件数据
        if (read(*touchFd, &inputEvent, sizeof(inputEvent)) != sizeof(inputEvent))
            continue;
        // 保存事件数据
        time = inputEvent.time, *touchInputEvent = inputEvent;
        // 事件类型
        switch (inputEvent.type) {
        case EVENT_ABS: { // 绝对坐标事件
            // 事件编码
            switch (inputEvent.code) {
            case ABS_X_POINT: { // X坐标
                if (startX == -1)
                    startX = inputEvent.value;
                if (timeXY == -1)
                    startTime = time, timeXY = 0;
                endX = inputEvent.value;
                break;
            }
            case ABS_Y_POINT: { // Y坐标
                if (startY == -1)
                    startY = inputEvent.value;
                if (timeXY == -1)
                    startTime = time, timeXY = 0;
                endY = inputEvent.value;
                break;
            }
            default:
                break;
            }
        }
        case EVENT_KEY: { // 按键事件
            // 事件编码
            switch (inputEvent.code) {
            case BTN_TOUCH: { // 有意义触摸事件
                // 触摸终止
                if (!inputEvent.value) {
                    // 结束时间
                    endTime = time;
                    // 显示屏与触摸屏匹配
                    endX = endX / TOUCH_SCREEN_X_PROPORTION, endY = endY / TOUCH_SCREEN_Y_PROPORTION;
                    startX = startX / TOUCH_SCREEN_X_PROPORTION, startY = startY / TOUCH_SCREEN_Y_PROPORTION;
                    if ((endX - startX) * (endX - startX) + (endY - startY) * (endY - startY) <= EVENT_CLICK_RADIUS * EVENT_CLICK_RADIUS)
                        if ((endTime.tv_sec - startTime.tv_sec) <= (EVENT_PRESS_DURATION - (endTime.tv_usec - startTime.tv_usec)) / (double)(1000 * 1000))
                            touchEvent.type = EVENT_CLICK; // 距离小于等于EVENT_CLICK_RADIUS、时间小于等于EVENT_PRESS_DURATION，点击事件
                        else
                            touchEvent.type = EVENT_PRESS; // 距离小于等于EVENT_CLICK_RADIUS、时间大于EVENT_PRESS_DURATION，长按事件
                    else
                        touchEvent.type = EVENT_SLIDE; // 距离大于EVENT_CLICK_RADIUS滑动事件
                    // 添加事件信息
                    touchEvent.endX = endX, touchEvent.endY = endY;
                    touchEvent.startX = startX, touchEvent.startY = startY;
                    touchEvent.endTime.tv_sec = endTime.tv_sec, touchEvent.endTime.tv_usec = endTime.tv_usec;
                    touchEvent.startTime.tv_sec = startTime.tv_sec, touchEvent.startTime.tv_usec = startTime.tv_usec;
                    // 加入事件队列
                    if (touchEvents->size() == EVENT_MAX)
                        touchEvents->pop_back();
                    touchEvents->insert(touchEvents->begin(), touchEvent);
                    // 恢复初始值
                    timeXY = -1;
                    endX = -1, endY = -1;
                    startX = -1, startY = -1;
                    time.tv_sec = 0, time.tv_usec = 0;
                    endTime.tv_sec = 0, endTime.tv_usec = 0;
                    startTime.tv_sec = 0, startTime.tv_usec = 0;
                    memset(&touchEvent, 0, sizeof(touchEvent));
                    memset(&inputEvent, 0, sizeof(inputEvent));
                }
                break;
            }
            default:
                break;
            }
        }
        default:
            break;
        }
    }
    // 退出线程
    pthread_exit(touchFd);
    return NULL;
}

Screen::Screen(const string &path, const size_t width, const size_t height) {
    void *screenMap;
    // 初始化数据
    this->touchEvents.clear(), this->wordMap.clear();
    this->touchFd = -1, this->touchTid = -1, this->touchSignal = 0;
    this->word.name = "", this->word.width = 0, this->word.height = 0;
    this->fd = -1, this->width = 0, this->heigth = 0, this->screenMap = NULL;
    memset(&this->touchParam, 0, sizeof(this->touchParam));
    memset(&this->touchEvent, 0, sizeof(this->touchEvent));
    memset(&this->touchInputEvent, 0, sizeof(this->touchInputEvent));
    memset(&this->bmp.bitmapfileheader, 0, sizeof(this->bmp.bitmapfileheader));
    memset(&this->bmp.bitmapinfoheader, 0, sizeof(this->bmp.bitmapinfoheader));
    vector< uint8_t >().swap(this->bmp.data), vector< RGBQUAD >().swap(this->bmp.rgbquad), vector< uint8_t >().swap(this->word.wordData);
    // 打开屏幕
    if ((this->fd = open(path.c_str(), O_RDWR)) == -1)
        throw runtime_error("open '" + path + "' error!\n");
    // 屏幕初始化
    this->width = width, this->heigth = height;
    // 映射屏幕
    if ((screenMap = mmap(NULL, this->width * this->heigth * sizeof(uint32_t), PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, 0)) == MAP_FAILED)
        throw runtime_error("mmap error!\n");
    this->screenMap = (uint32_t *)screenMap;
    // 字体初始化
    this->wordMap = word_init();
}

Screen::~Screen() {
    // 卸载位图
    this->uload_bmp();
    // 卸载字体
    this->uload_word();
    // 关闭触摸
    this->uload_touch();
    // 关闭映射
    if (this->screenMap != NULL)
        munmap(this->screenMap, this->width * this->heigth * sizeof(uint32_t));
    // 关闭文件
    if (this->fd != -1)
        close(this->fd);
}

Screen::INPUTEVENT &Screen::get_touch_input_event() {
    return this->touchInputEvent;
}

Screen::TOUCHEVENT &Screen::get_touch() {
    // 事件存在
    if (this->touchEvents.size()) {
        // 获取尾元素
        this->touchEvent = this->touchEvents.back();
        // 删除尾元素
        this->touchEvents.pop_back();
        return this->touchEvent;
    }
    // 清空数据
    memset(&this->touchEvent, 0, sizeof(this->touchEvent));
    return this->touchEvent;
}

Screen &Screen::clear_touch() {
    // 清空事件
    memset(&this->touchEvent, 0, sizeof(this->touchEvent));
    // 清空输入事件
    memset(&this->touchInputEvent, 0, sizeof(this->touchInputEvent));
    // 清空事件队列
    this->touchEvents.clear();
    return *this;
}

Screen &Screen::load_touch(const string &path) {
    // 打开触摸
    if ((this->touchFd = open(path.c_str(), O_RDWR)) == -1)
        throw runtime_error("open '" + path + "' error!\n");
    // 设置触摸事件最大值
    this->touchEvents.reserve(EVENT_MAX);
    // 创建线程
    this->touchSignal = 1;
    this->touchParam.touchFd = &this->touchFd;
    this->touchParam.touchTid = &this->touchTid;
    this->touchParam.touchSignal = &this->touchSignal;
    this->touchParam.touchEvents = &this->touchEvents;
    this->touchParam.touchInputEvent = &this->touchInputEvent;
    if (pthread_create(&this->touchTid, NULL, touch_thread, &this->touchParam)) {
        close(this->touchFd);
        throw runtime_error("load_touch pthread_create error!\n");
    }
    return *this;
}

Screen &Screen::uload_touch() {
    // 关闭线程
    if (this->touchSignal != 0)
        this->touchSignal = 0;
    // 关闭文件
    if (this->touchFd != -1)
        close(this->touchFd);
    // 清空线程ID
    if (this->touchTid != -1)
        this->touchTid = -1;
    // 清空事件集合
    vector< TOUCHEVENT >().swap(this->touchEvents);
    // 清空触摸参数
    memset(&this->touchParam, 0, sizeof(this->touchParam));
    // 清空触摸事件
    memset(&this->touchEvent, 0, sizeof(this->touchEvent));
    // 清空触摸输入事件
    memset(&this->touchInputEvent, 0, sizeof(this->touchInputEvent));
    return *this;
}

Screen &Screen::draw_fill(const POINT &point, const uint32_t width, const uint32_t height, uint32_t color) {
    uint32_t x, y, endx, endy;
    // 填充矩形
    for (x = point.x, endx = point.x + width; x < endx; x++)
        for (y = point.y, endy = point.y + height; y < endy; y++)
            if (x < this->width && y < this->heigth)
                this->screenMap[y * this->width + x] = color;
    return *this;
}

Screen &Screen::draw_point(const POINT &point, const uint32_t color) {
    // 绘制点
    if (point.x < this->width && point.y < this->heigth)
        this->screenMap[point.y * this->width + point.x] = color;
    return *this;
}

Screen &Screen::draw_points(const vector< POINT > &points, const uint32_t color) {
    size_t i, size = points.size();
    for (i = 0; i < size; i++)
        this->draw_point(points[i], color);
    return *this;
}

Screen &Screen::draw_line(const LINESEGMENT &lineSegment, const uint32_t width, const uint32_t color) {
    int32_t x, y, endx, endy, up, down, x1 = lineSegment.x1, y1 = lineSegment.y1, x2 = lineSegment.x2, y2 = lineSegment.y2;
    double k = (1.0 * y2 - y1) / (1.0 * x2 - x1); // 计算斜率
    double b = y1 - k * x1;                       // 计算截距
    // 计算线宽
    if (width == 0)
        return *this;
    else if (width % 2 == 0)
        up = down = width / 2;
    else
        up = width / 2 + 1, down = width / 2;
    // 绘制线段
    for (x = x1 <= x2 ? x1 : x2, endx = x1 > x2 ? x1 : x2; x <= endx; x++) {
        if (x >= 0 && x < this->width) {
            // 绘制线段中间部分和上半部分
            for (y = k * x + b, endy = y + up; y < endy; y++)
                if (y >= 0 && y < this->heigth)
                    this->screenMap[y * this->width + x] = color;
            // 绘制线段下半部分
            for (y = k * x + b - 1, endy = y - down; y >= endy; y--)
                if (y >= 0 && y < this->heigth)
                    this->screenMap[y * this->width + x] = color;
        }
    }
    return *this;
}

Screen &Screen::draw_lines(const vector< LINESEGMENT > &lineSegments, const uint32_t width, const uint32_t color) {
    size_t i, size = lineSegments.size();
    // 绘制线段
    for (i = 0; i < size; i++)
        this->draw_line(lineSegments[i], width, color);
    return *this;
}

Screen &Screen::draw_react(const REACT &react, const uint32_t width, uint32_t color) {
    uint32_t x, y, endx, endy;
    uint32_t x0 = react.x + width, x0End = react.x + react.width - width;
    uint32_t y0 = react.y + width, y0End = react.y + react.height - width;
    if (width > react.width || width > react.height)
        return *this;
    // 绘制矩形
    for (x = react.x, endx = react.x + react.width; x < endx; x++)
        for (y = react.y, endy = react.y + react.height; y < endy; y++)
            if (x < this->width && y < this->heigth && !(x >= x0 && x < x0End && y >= y0 & y < y0End))
                this->screenMap[y * this->width + x] = color;
    return *this;
}

Screen &Screen::draw_reacts(const vector< REACT > &reacts, const uint32_t width, uint32_t color) {
    size_t i, size = reacts.size();
    for (i = 0; i < size; i++)
        this->draw_react(reacts[i], width, color);
    return *this;
}

Screen &Screen::draw_circle(const CIRCLE &circle, const uint32_t width, const uint32_t color) {
    int32_t x, y, endx, endy, square, ri, ris, rs, r = circle.r, x0 = circle.x, y0 = circle.y;
    ri = r - width <= 0 ? 0 : r - width; // 内部圆半径
    rs = r * r, ris = ri * ri;           // 外部圆半径平方、内部圆半径
    if (width == 0)
        return *this;
    // 绘制圆
    for (x = x0 - r, endx = x0 + r; x <= endx; x++)
        for (y = y0 - r, endy = y0 + r; y <= endy; y++) {
            square = (x - x0) * (x - x0) + (y - y0) * (y - y0);
            if (x >= 0 && x < this->width && y >= 0 && y < this->heigth && (square <= rs && square > ris || square == 0 && width == r))
                this->screenMap[y * this->width + x] = color;
        }
    return *this;
}

Screen &Screen::draw_circles(const vector< CIRCLE > &circles, const uint32_t width, const uint32_t color) {
    size_t i, size = circles.size();
    for (i = 0; i < size; i++)
        this->draw_circle(circles[i], width, color);
    return *this;
}

WORD &Screen::get_word() {
    return this->word;
}

Screen &Screen::uload_word() {
    // 清空数据
    this->word.name = "", this->word.width = 0, this->word.height = 0;
    // 清空字体数据
    vector< uint8_t >().swap(this->word.wordData);
    return *this;
}

Screen &Screen::load_word(const string &word) {
    // 字不存在
    if (this->wordMap.find(word) == this->wordMap.end())
        throw runtime_error("'" + word + "' non-existent!\n");
    // 加载数据
    this->word.name = this->wordMap[word].name;
    this->word.width = this->wordMap[word].width;
    this->word.height = this->wordMap[word].height;
    this->word.wordData = this->wordMap[word].wordData;
    return *this;
}

Screen &Screen::draw_word(const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t color) {
    vector< vector< uint32_t > > inRGB, outRGB;
    vector< uint8_t > &originWord = this->word.wordData;
    uint32_t i, bit, x, y, endx, endy, originWidth = this->word.width, originHeight = this->word.height, originSize = this->word.wordData.size();
    if (originWidth == 0 || originHeight == 0 || originSize == 0)
        return *this;
    // 构建字体二维RGB数组
    inRGB.resize(originHeight);
    for (i = 0; i < originHeight; i++)
        inRGB[i].resize(originWidth);
    for (i = 0; i < originSize; i++)
        for (bit = 0; bit < 8; bit++)
            inRGB[i / (originWidth / 8)][(i * 8 + bit) % originWidth] = ((originWord[i] << bit) & 0x80) ? 0xff000000 | color : 0x00000000;
    // 缩放
    if (originWidth == width && originHeight == height)
        inRGB.swap(outRGB);
    else
        this->bilinera_interpolation(outRGB, width, height, inRGB, originWidth, originHeight);
    // 显示
    for (y = y0, endy = y0 + height > this->heigth ? this->heigth : y0 + height; y < endy; y++)
        for (x = x0, endx = x0 + width > this->width ? this->width : x0 + width; x < endx; x++)
            this->screenMap[y * this->width + x] = (outRGB[y - y0][x - x0] >> 24 != 0) ? outRGB[y - y0][x - x0] & 0x00ffffff : this->screenMap[y * this->width + x];
    return *this;
}

Screen &Screen::draw_words(const string &words, const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t columnSpacing, uint32_t rowSpacing, const uint32_t color) {
    string s;
    uint32_t i, x = x0, y = y0, size = words.size();
    for (i = 0; i < size; i++) {
        s.clear();
        if (words[i] == '\n') {
            x = x0, y += height + rowSpacing;
            continue;
        }
        if (words[i] == '\r') {
            x = x0, y = y;
            continue;
        }
        if (words[i] == '\t') {
            x = x0 + 2 * (width + columnSpacing), y = y;
            continue;
        }
        if (words[i] == ' ') {
            x = x0 + (uint32_t)round((width + columnSpacing) * 1.0 / 2), y = y;
            continue;
        }
        if (words[i] >= 0 && words[i] < 128)
            s += words[i];
        else {
            s += words[i];
            s += words[++i];
            s += words[++i];
        }
        this->load_word(s).draw_word(x, y, width, height, color);
        x += width + columnSpacing;
    }
    return *this;
}

Screen &Screen::draw_nums(const double &nums, const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t decimalPlaces, const uint32_t columnSpacing, uint32_t rowSpacing, const uint32_t color) {
    char buf[36] = {0}, format[24];
    sprintf(format, "%%.%dlf", decimalPlaces > 18 ? 18 : decimalPlaces);
    sprintf(buf, format, nums);
    this->draw_words(buf, x0, y0, width, height, columnSpacing, rowSpacing, color);
    return *this;
}

Screen::BMP &Screen::get_bmp() {
    return this->bmp;
}

Screen &Screen::uload_bmp() {
    // 清空图片数据
    vector< uint8_t >().swap(this->bmp.data);
    // 清空调色板数据
    vector< RGBQUAD >().swap(this->bmp.rgbquad);
    // 清空文件头
    memset(&this->bmp.bitmapfileheader, 0, sizeof(this->bmp.bitmapfileheader));
    // 清空信息头
    memset(&this->bmp.bitmapinfoheader, 0, sizeof(this->bmp.bitmapinfoheader));
    return *this;
}

Screen &Screen::load_bmp(const string &path) {
    int32_t i, end, fd;
    // 打开图片
    if ((fd = open(path.c_str(), O_RDWR)) == -1)
        throw runtime_error("open '" + path + "' error!\n");
    // 读取文件头
    read(fd, &this->bmp.bitmapfileheader, sizeof(this->bmp.bitmapfileheader));
    // 非bmp图片异常
    if (this->bmp.bitmapfileheader.bfType != 0x4D42) {
        close(fd);
        throw runtime_error("'" + path + "' is not a bmp file!\n");
    };
    // 读取信息头
    read(fd, &this->bmp.bitmapinfoheader, sizeof(this->bmp.bitmapinfoheader));
    // 读取调色板
    if (!(this->bmp.bitmapinfoheader.biBitCount == 16 || this->bmp.bitmapinfoheader.biBitCount == 24 || this->bmp.bitmapinfoheader.biBitCount == 32)) {
        end = this->bmp.bitmapinfoheader.biClrUsed == 0 ? 1 << this->bmp.bitmapinfoheader.biBitCount : this->bmp.bitmapinfoheader.biClrUsed;
        this->bmp.rgbquad.resize(end);
        for (i = 0; i < end; i++)
            read(fd, &this->bmp.rgbquad[i], sizeof(this->bmp.rgbquad[i]));
    }
    // 读取图片数据
    end = this->bmp.bitmapinfoheader.biSizeImage;
    this->bmp.data.resize(end);
    for (i = 0; i < end; i++)
        read(fd, &this->bmp.data[i], sizeof(this->bmp.data[i]));
    // 关闭文件
    close(fd);
    return *this;
}

Screen &Screen::draw_bmp(const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t targetX0, const uint32_t targetY0, const size_t targetWidth, const size_t targetHeight, const uint32_t defaultColor) {
    uint32_t x, y, b, g, r, i, index, endx, endy;
    vector< uint8_t > &originData = this->bmp.data;
    vector< vector< uint32_t > > originRGB, targetRGB;
    uint32_t fillBytes = this->bmp.bitmapinfoheader.biWidth * 3 % 4 == 0 ? 0 : 4 - this->bmp.bitmapinfoheader.biWidth * 3 % 4, originWidth = this->bmp.bitmapinfoheader.biWidth, originHeight = this->bmp.bitmapinfoheader.biHeight;
    // 仅支持24位BMP图片
    if (this->bmp.bitmapfileheader.bfType != 0x4D42)
        throw runtime_error("only supports BMP format images!\n");
    if (this->bmp.bitmapinfoheader.biBitCount != 24)
        throw runtime_error("only supports 24 bit images!\n");
    // 排除填充字节、上下颠倒、二维RGB数组
    originRGB.resize(originHeight);
    for (y = 0, index = 0; y < originHeight; y++) {
        originRGB[originHeight - y - 1].resize(originWidth);
        for (x = 0; x < originWidth; x++) {
            b = originData[index++];
            g = originData[index++];
            r = originData[index++];
            originRGB[originHeight - y - 1][x] = r << 16 | g << 8 | b;
        }
        for (i = 0; i < fillBytes; i++)
            index++;
    }
    // 缩放
    if (originWidth == targetWidth && originHeight == targetHeight)
        originRGB.swap(targetRGB);
    else
        this->bilinera_interpolation(targetRGB, targetWidth, targetHeight, originRGB, originWidth, originHeight);
    // 显示
    for (y = y0, endy = y0 + height > this->heigth ? this->heigth : y0 + height; y < endy; y++)
        for (x = x0, endx = x0 + width > this->width ? this->width : x0 + width; x < endx; x++)
            this->screenMap[y * this->width + x] = (y - y0 + targetY0 >= targetHeight || x - y0 + targetX0 >= targetWidth) ? (defaultColor & 0xff000000 ? this->screenMap[y * this->width + x] : defaultColor) : targetRGB[y - y0 + targetY0][x - y0 + targetX0];
    return *this;
}

vector< size_t > Screen::bilinera_interpolation(vector< vector< uint32_t > > &out, const size_t outWidth, const size_t outHeight, const vector< vector< uint32_t > > &in, const size_t inWidth, const size_t inHeight) {
    uint8_t c, r, g, b;
    vector< size_t > ans;
    uint32_t x, y, x1, y1, x2, y2, x3, y3, x4, y4;
    double x0, y0, x0i, y0i, distanceX, distanceY, hZoom = (double)outHeight / (double)inHeight, wZoom = (double)outWidth / (double)inWidth;
    // 双线性插值
    out.resize(outHeight);
    for (y = 0; y < outHeight; y++) {
        out[y].resize(outWidth);
        for (x = 0; x < outWidth; x++) {
            // 源浮点坐标、源整型坐标
            x0 = x / wZoom, y0 = y / hZoom;
            x0i = (int)x0, y0i = (int)y0;
            // A、B、C、D点坐标
            x1 = x0i, y1 = y0i;
            x2 = x0i + 1, y2 = y0i;
            x3 = x0i, y3 = y0i + 1;
            x4 = x0i + 1, y4 = y0i + 1;
            // 源浮点坐标距A点距离
            distanceX = x0 - x0i, distanceY = y0 - y0i;
            // 最后一列
            if (x0i + 1 >= inWidth)
                x2 = x1, x4 = x3;
            // 最后一行
            if (y0i + 1 >= inHeight)
                y3 = y1, y4 = y2;
            // 计算RGB
            c = (uint8_t)(in[y1][x1] >> 24 & 0x000000ff) * (1 - distanceX) * (1 - distanceY) + (uint8_t)(in[y2][x2] >> 24 & 0x000000ff) * distanceX * (1 - distanceY) + (uint8_t)(in[y3][x3] >> 24 & 0x000000ff) * (1 - distanceX) * distanceY + (uint8_t)(in[y4][x4] >> 24 & 0x000000ff) * distanceX * distanceY;
            r = (uint8_t)(in[y1][x1] >> 16 & 0x000000ff) * (1 - distanceX) * (1 - distanceY) + (uint8_t)(in[y2][x2] >> 16 & 0x000000ff) * distanceX * (1 - distanceY) + (uint8_t)(in[y3][x3] >> 16 & 0x000000ff) * (1 - distanceX) * distanceY + (uint8_t)(in[y4][x4] >> 16 & 0x000000ff) * distanceX * distanceY;
            g = (uint8_t)(in[y1][x1] >> 8 & 0x000000ff) * (1 - distanceX) * (1 - distanceY) + (uint8_t)(in[y2][x2] >> 8 & 0x000000ff) * distanceX * (1 - distanceY) + (uint8_t)(in[y3][x3] >> 8 & 0x000000ff) * (1 - distanceX) * distanceY + (uint8_t)(in[y4][x4] >> 8 & 0x000000ff) * distanceX * distanceY;
            b = (uint8_t)(in[y1][x1] >> 0 & 0x000000ff) * (1 - distanceX) * (1 - distanceY) + (uint8_t)(in[y2][x2] >> 0 & 0x000000ff) * distanceX * (1 - distanceY) + (uint8_t)(in[y3][x3] >> 0 & 0x000000ff) * (1 - distanceX) * distanceY + (uint8_t)(in[y4][x4] >> 0 & 0x000000ff) * distanceX * distanceY;
            // 写入
            out[y][x] = c << 24 | r << 16 | g << 8 | b;
        }
    }
    ans.resize(2);
    ans[0] = outWidth, ans[1] = outHeight;
    return ans;
}